<template>
  <el-button
    v-bind="buttonProps"
    :loading="isLoading"
    :disabled="isDisabled"
    @click="handleClick"
  >
    <template #loading>
      <el-icon class="is-loading">
        <component :is="loadingIcon" />
      </el-icon>
    </template>
    
    <el-icon v-if="!isLoading && icon" class="button-icon">
      <component :is="icon" />
    </el-icon>
    
    <span>{{ currentText }}</span>
  </el-button>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { Loading } from '@element-plus/icons-vue'
import type { ButtonProps } from 'element-plus'

export interface LoadingButtonProps extends Partial<ButtonProps> {
  // 加载状态
  loading?: boolean
  // 按钮文本
  text?: string
  // 加载中文本
  loadingText?: string
  // 自动加载（点击后自动进入加载状态）
  autoLoading?: boolean
  // 加载持续时间（毫秒），0表示手动控制
  loadingDuration?: number
  // 图标
  icon?: any
  // 加载图标
  loadingIcon?: any
  // 点击防抖延迟（毫秒）
  debounce?: number
  // 确认提示
  confirmText?: string
  // 确认类型
  confirmType?: 'warning' | 'info' | 'success' | 'error' | 'question'
}

const props = withDefaults(defineProps<LoadingButtonProps>(), {
  loading: false,
  text: '确定',
  loadingText: '处理中...',
  autoLoading: false,
  loadingDuration: 0,
  loadingIcon: Loading,
  debounce: 300,
  confirmType: 'warning'
})

const emit = defineEmits<{
  click: [event: MouseEvent]
  loadingChange: [loading: boolean]
}>()

const internalLoading = ref(false)
const isDebouncing = ref(false)
let debounceTimer: NodeJS.Timeout | null = null
let loadingTimer: NodeJS.Timeout | null = null

// 最终加载状态
const isLoading = computed(() => props.loading || internalLoading.value)

// 是否禁用
const isDisabled = computed(() => isLoading.value || isDebouncing.value)

// 当前显示文本
const currentText = computed(() => {
  return isLoading.value ? props.loadingText : props.text
})

// 按钮属性（排除自定义属性）
const buttonProps = computed(() => {
  const excluded = [
    'loading', 'text', 'loadingText', 'autoLoading', 
    'loadingDuration', 'icon', 'loadingIcon', 'debounce',
    'confirmText', 'confirmType'
  ]
  const result: Record<string, any> = {}
  
  Object.keys(props).forEach(key => {
    if (!excluded.includes(key)) {
      result[key] = (props as any)[key]
    }
  })
  
  return result
})

// 监听加载状态变化
watch(isLoading, (val) => {
  emit('loadingChange', val)
})

// 开始加载
const startLoading = () => {
  if (props.autoLoading && !props.loading) {
    internalLoading.value = true
    
    // 如果设置了加载持续时间，自动停止
    if (props.loadingDuration > 0) {
      loadingTimer = setTimeout(() => {
        stopLoading()
      }, props.loadingDuration)
    }
  }
}

// 停止加载
const stopLoading = () => {
  if (loadingTimer) {
    clearTimeout(loadingTimer)
    loadingTimer = null
  }
  internalLoading.value = false
}

// 处理点击事件
const handleClick = async (event: MouseEvent) => {
  // 如果正在防抖或加载中，忽略点击
  if (isDebouncing.value || isLoading.value) {
    return
  }

  // 确认提示
  if (props.confirmText) {
    try {
      const { ElMessageBox } = await import('element-plus')
      await ElMessageBox.confirm(
        props.confirmText,
        '确认操作',
        {
          type: props.confirmType,
          confirmButtonText: '确定',
          cancelButtonText: '取消'
        }
      )
    } catch {
      return // 用户取消了操作
    }
  }

  // 防抖处理
  if (props.debounce > 0) {
    isDebouncing.value = true
    debounceTimer = setTimeout(() => {
      isDebouncing.value = false
    }, props.debounce)
  }

  // 开始加载
  startLoading()

  // 触发点击事件
  emit('click', event)
}

// 清理定时器
const cleanup = () => {
  if (debounceTimer) {
    clearTimeout(debounceTimer)
    debounceTimer = null
  }
  if (loadingTimer) {
    clearTimeout(loadingTimer)
    loadingTimer = null
  }
}

// 组件卸载时清理
import { onBeforeUnmount } from 'vue'
onBeforeUnmount(cleanup)

// 暴露方法
defineExpose({
  startLoading,
  stopLoading,
  isLoading: () => isLoading.value
})
</script>

<style scoped>
.button-icon {
  margin-right: 6px;
}

.is-loading {
  margin-right: 6px;
  animation: rotating 2s linear infinite;
}

@keyframes rotating {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

/* 确保文本不换行 */
.el-button span {
  white-space: nowrap;
}
</style>
